//
// Created by ningjian on 18-6-6.
//

#include <netinet/in.h>
#include "StreamToMP4.hpp"
#include "MuxerToMP4.hpp"


StreamToMP4::StreamToMP4(std::string path_prefix,
                         long timespace,
                         AVCodecID input_v_codec_id,
                         AVCodecID input_a_codec_id) {
    this->path_prefix = path_prefix;

    this->timespace = timespace;

    this->input_v_codec_id = input_v_codec_id;
    this->input_a_codec_id = input_a_codec_id;
}


bool StreamToMP4::Init() {


    if (input_v_codec_id != AV_CODEC_ID_NONE) {
        v_input_code = avcodec_find_decoder(input_v_codec_id);
        v_input_codec = avcodec_alloc_context3(v_input_code);
        v_input_parse = av_parser_init(v_input_code->id);
        avcodec_open2(v_input_codec, v_input_code, NULL);

        av_init_packet(&v_packet);
        v_frame = av_frame_alloc();
    }

    return true;
}

bool StreamToMP4::WriteAudioFrameData(int f_len, uint8_t *f_data) {
    //音频数据依赖视频，只有音频则不保存mp4
    if(is_init_v_input){
        if (!p_file_a) {
            p_file_a = fopen(a_tmp_name.c_str(), "wb");

        }
        fwrite(f_data,1,f_len,p_file_a);

        return true;
    }



    // 只有音频的情况
    if (!is_init_a_input ) {
        is_init_a_input = true;
        start_tmp_time = (long) time(NULL);
        a_tmp_name = path_prefix + "_" + std::to_string(start_tmp_time) + ".aac";
        p_file_a = fopen(a_tmp_name.c_str(), "wb");
        fwrite(f_data,1,f_len,p_file_a);
        return true;
    }

    long now =  (long) time(NULL);
    if(now - start_tmp_time > timespace){ //必须要有SPS and PPS

        fclose(p_file_a);

        start_tmp_time = now;
        a_tmp_name =  path_prefix + "_" + std::to_string(start_tmp_time) + ".aac";
        p_file_a = fopen(a_tmp_name.c_str(), "wb");
        fwrite(f_data,1,f_len,p_file_a);
        return true;

    }

    if( p_file_a ){
        fwrite(f_data,1,f_len,p_file_a);
    }

    return true;


}

bool StreamToMP4::WriteVideoFrameData(int f_len, uint8_t *f_data) {

    if (!is_init_v_input && f_data[4] == 0x67) {//必须要有SPS and PPS
        is_init_v_input = true;
        if(start_tmp_time == 0){
            start_tmp_time = (long) time(NULL);  //有可能先收到音频数据
        }

        v_tmp_name = path_prefix + "_" + std::to_string(start_tmp_time) + ".h264";
        a_tmp_name =  path_prefix + "_" + std::to_string(start_tmp_time) + ".aac";
        p_file_v = fopen(v_tmp_name.c_str(), "wb");
        fwrite(f_data,1,f_len,p_file_v);
        return true;
    }

    long now =  (long) time(NULL);
    if(now - start_tmp_time > timespace && f_data[4] == 0x67){ //必须要有SPS and PPS

        fclose(p_file_v);
        if(p_file_a){
            fclose(p_file_a);
            p_file_a = NULL;
        }
        //    // convert H264 file to mp4 file
        std::string save_name = path_prefix + "_" + std::to_string(start_tmp_time) + ".mp4";
        muxer_main((char*)v_tmp_name.c_str(),(char*)a_tmp_name.c_str(),(char*)save_name.c_str(),"");

        start_tmp_time = now;
        v_tmp_name = path_prefix + "_" + std::to_string(start_tmp_time) + ".h264";
        a_tmp_name =  path_prefix + "_" + std::to_string(start_tmp_time) + ".aac";
        p_file_v = fopen(v_tmp_name.c_str(), "wb");
        fwrite(f_data,1,f_len,p_file_v);
        return true;

    }

    if( p_file_v ){
        fwrite(f_data,1,f_len,p_file_v);
    }

    return true;
    // 解码部分
//    uint8_t *cur_ptr = f_data;
//    int cur_size = f_len;
//
//    while (!is_init_v_input && cur_size > 0) {
//        int len = av_parser_parse2(
//                v_input_parse, v_input_codec,
//                &v_packet.data, &v_packet.size,
//                cur_ptr, cur_size,
//                AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
//        std::cout << "coded_height " << v_input_codec->coded_height << std::endl;
//        std::cout << "len " << len << " pkt.size " << v_packet.size << std::endl;
//        cur_ptr += len;
//        cur_size -= len;
//
//        if (v_packet.size == 0)
//            continue;
//
//
//        if (!is_init_v_input) {//还没有初始化
//
//            int ret = avcodec_send_packet(v_input_codec, &v_packet);
//            if (ret < 0) {
//                fprintf(stderr, "Error sending a packet for decoding\n");
//                return false;
//            }
//
//            while (ret >= 0) {
//                ret = avcodec_receive_frame(v_input_codec, v_frame);
//                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
//                    break;
//                else if (ret < 0) {
//                    fprintf(stderr, "Error during decoding\n");
//                    return false;
//                }
//                printf("saving frame %3d\n", v_input_codec->frame_number);
//
//
//                is_init_v_input = true;
//            }
//        }
//
//    }


    return true;
}

void StreamToMP4::Finsh() {

    if(p_file_a){
        fclose(p_file_a);
    }

    if(p_file_v){
        fclose(p_file_v);
        std::string save_name = path_prefix + "_" + std::to_string(start_tmp_time) + ".mp4";
        muxer_main((char*)v_tmp_name.c_str(),(char*)a_tmp_name.c_str(),(char*)save_name.c_str(),"");
    }
}




